home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’96
/
Venus
/
main.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-22
|
8KB
|
263 lines
/*
************************************************************************
*
* Root Module
* Note on animation.
* We don't use null events to do animation: all animation is done in the
* drawing function itself. To activate animation, we invalidate regions
* covering both 2d and 3d views, and set is_flying to TRUE. Invalidating regions
* guarantees that visRgn of our on-screen window is set to include both views,
* and it makes sure that the next event would be an Update event. This event
* is eventually relayed to our 2d_view's and 3d_view's drawing functions.
* When is_flying is set to TRUE, these functions not only draw a window, but
* perform a few cycles of animation as well. Before they return, they invalidate
* the regions again, thus making sure that a new Update event would be generated,
* and they'll be called again.
*
************************************************************************
*/
#include "fractal_map.h"
#include "mymenv.h"
#include "EventHandlers.h"
#include "ValueControl.h"
#include "ImageViews.h"
#include "filter.h"
//#include "profiler.h"
class VenusDialog : public ModelessDialog
{
enum { item_Go = 1, item_Cancel = 2, item_2dview = 3, item_3dview = 4,
item_ze=5, item_ze_val=6, item_ze_text=7,
item_beta=8, item_beta_val=9, item_beta_text=10,
item_Ou=11, item_Ou_val=12, item_Ou_text=13,
item_Ov=14, item_Ov_val=15, item_Ov_text=16,
item_zc=17, item_zc_val=18, item_zc_text=19,
item_zf=20, item_zf_val=21, item_zf_text=22,
item_fps=24 };
enum { dlog_id = 128 };
ProjectionParameters projection_parms;
Boolean handle_item_hit(const int item_no);
Boolean handle_activate(Boolean onoff); // Handle suspend/resume events
ValueControl eyepoint_elevation;
ValueControl beta; // Local coordinates scaling factor
ValueControl Ou; // Origin of the local coordinate ref Pt
ValueControl Ov;
ValueControl z_cutoff; // Coefficients to determine elevation from
ValueControl elevation_factor; // the map's "elevation code"
int time_started; // Time (ticks) started flying the last time
int frame_counter;
ImageView image_2d_view;
ThreeDView image_3d_view;
void draw_user_item(const int item_no);
void start_flight(void);
void stop_flight(void);
Boolean is_flying; // Is our plane moving?
public:
VenusDialog(const IMAGE& image);
};
VenusDialog::VenusDialog(const IMAGE& image)
: ModelessDialog(dlog_id), image_2d_view(image),
image_3d_view(image,image_2d_view.where_is_viewer(),projection_parms),
beta(4,1), is_flying(FALSE)
{
// Late construction of items, after the dialog itself
// has been initialized
image_2d_view.bind(*this,item_2dview);
eyepoint_elevation.bind(ControlItem(*this,item_ze),NumberItem(*this,item_ze_val));
beta.bind(ControlItem(*this,item_beta),NumberItem(*this,item_beta_val));
Ou.bind(ControlItem(*this,item_Ou),NumberItem(*this,item_Ou_val));
Ov.bind(ControlItem(*this,item_Ov),NumberItem(*this,item_Ov_val));
z_cutoff.bind(ControlItem(*this,item_zc),NumberItem(*this,item_zc_val));
elevation_factor.bind(ControlItem(*this,item_zf),NumberItem(*this,item_zf_val));
NumberItem(*this,item_fps).draw(0);
projection_parms.ze = eyepoint_elevation;
projection_parms.beta = beta;
projection_parms.Ou = Ou;
projection_parms.Ov = Ov;
projection_parms.z_cutoff = z_cutoff;
projection_parms.elevation_factor = elevation_factor;
image_3d_view.bind(*this,item_3dview);
show();
}
// Commencing and terminating the flight
void VenusDialog::start_flight(void)
{
is_flying = TRUE;
ModelessDialog::ControlItem(*this,item_Go).set_title("\pStop");
frame_counter = 0;
time_started = TickCount();
}
void VenusDialog::stop_flight(void)
{
is_flying = FALSE;
ModelessDialog::ControlItem(*this,item_Go).set_title("\pGo");
const int time_elapsed = TickCount() - time_started; // in Ticks
NumberItem(*this,item_fps).draw(
time_elapsed == 0 ? 0 : (60*frame_counter)/time_elapsed );
}
Boolean VenusDialog::handle_item_hit(const int item_no)
{
SetNewGrafPtr dialog_grafport(our_window());
switch(item_no)
{
case item_Cancel:
return FALSE;
case item_ze:
projection_parms.ze = eyepoint_elevation;
image_3d_view.re_project();
return TRUE;
case item_beta:
projection_parms.beta = beta;
image_3d_view.re_project();
return TRUE;
case item_Ou:
projection_parms.Ou = Ou;
image_3d_view.re_project();
return TRUE;
case item_Ov:
projection_parms.Ov = Ov;
image_3d_view.re_project();
return TRUE;
case item_zc:
projection_parms.z_cutoff = z_cutoff;
image_3d_view.re_project();
return TRUE;
case item_zf:
projection_parms.elevation_factor = elevation_factor;
image_3d_view.re_project();
return TRUE;
case item_Go:
if( is_flying )
stop_flight();
else
start_flight();
image_2d_view.force_redraw();
image_3d_view.force_redraw();
return TRUE;
default:
return TRUE;
}
}
// A relay to draw specific user items
// See a note on animation above
void VenusDialog::draw_user_item(const int item_no)
{
const int turns_per_cycle = 30;
switch(item_no)
{
case item_2dview:
if( is_flying )
{
for(register int i=0; i<turns_per_cycle; i++)
image_2d_view.do_one_turn(),
image_3d_view.re_project();
image_2d_view.force_redraw(); // That would make sure that the next call
image_3d_view.force_redraw(); // to WaitNextEvent would get another update
frame_counter += turns_per_cycle;
} // event, and this function would be called again
else
image_2d_view.draw();
break;
case item_3dview:
if( !is_flying ) // when flying, the window has been
image_3d_view.draw(); // already redrawn, see case above
break;
default:
_die("couldn't draw user item %d",item_no);
}
}
// Handle suspend/resume events: stop flying on
// a suspend event (flying takes too much time,
// it's unreasonable to take so much when
// running in background)
Boolean VenusDialog::handle_activate(Boolean onoff)
{
if( !onoff && is_flying )
handle_item_hit(item_Go);
return TRUE;
}
// Making elevation maps to fly around to
class MakeTestImage : public LazyImage // this one makes a couple of pyramids
{
void fill_in(IMAGE& im) const
{
const int ncols = im.q_ncols();
for(register int j=-20; j<20; j++)
for(register int i=-5; i<5; i++)
im(64+i,j+ncols/2) = 128 - 5*abs(i+j),
im(64+40+i,j+ncols/2) = 180 - 7*abs(i+j);
}
public:
MakeTestImage(void) : LazyImage(256,256,8) {}
};
class GaussClouds : public FractalMap
{
public:
GaussClouds(const card order)
: FractalMap(order) {}
// Well-known Gaussian random number generator
// Note rand() returns a number [0,2^15-1],
// that is, within [0,1] with a 15-bit implicit
// fraction
inline int get_noise(const card scale) const {
long sum = 0;
for(register int i=0; i<12; i++)
sum += rand(); // keep the result within
return (scale * (sum-(6<<15)))>>17; } // [-scale/2,scale/2]
};
void main(void)
{
Initialize_MAC();
GetDateTime((unsigned long *)&qd.randSeed);
Random(); Random(); Random(); // Just randomizing
srand(qd.randSeed);
#if 1
IMAGE image = FractalMap(8); // Get gaussian clouds and smooth them a bit
// IMAGE image = GaussClouds(8); // Get gaussian clouds and smooth them a bit
FilterIt(image).conv(conv_kernel(1,1,1,CommonDenom(3))).clip_to_intensity_range();
#else
// IMAGE image = FractalMap(8);
IMAGE image = MakeTestImage();
#endif
VenusDialog venus_dialog(image);
EventHandler event_handler(venus_dialog,0);
//ProfilerInit(collectDetailed,bestTimeBase,150,15);
//ProfilerSetStatus(0);
event_handler.loop();
//ProfilerDump("\pprofiler info");
//ProfilerTerm();
// alert("Done");
}